/*
 * Copyright [2022] [https://www.xiaonuo.vip]
 *
 * Snowy采用APACHE LICENSE 2.0开源协议，您在使用过程中，需要注意以下几点：
 *
 * 1.请不要删除和修改根目录下的LICENSE文件。
 * 2.请不要删除和修改Snowy源码头部的版权声明。
 * 3.本项目代码可免费商业使用，商业使用请保留源码和相关描述文件的项目出处，作者声明等。
 * 4.分发源码时候，请注明软件出处 https://www.xiaonuo.vip
 * 5.不可二次分发开源参与同类竞品，如有想法可联系团队xiaonuobase@qq.com商议合作。
 * 6.若您的项目无法满足以上几点，需要更多功能代码，获取Snowy商业授权许可，请在官网购买授权，地址为 https://www.xiaonuo.vip
 */
package cn.lixunims.ims.modular.basics.service.impl;

import cn.afterturn.easypoi.cache.manager.POICacheManager;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.lixunims.common.util.CommonDownloadUtil;
import cn.lixunims.common.util.CommonResponseUtil;
import cn.lixunims.ims.modular.basics.entity.ImsBankAccount;
import cn.lixunims.ims.modular.basics.entity.ImsWarehouse;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.handler.context.CellWriteHandlerContext;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.alibaba.excel.write.style.row.AbstractRowHeightStyleStrategy;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.poi.ss.usermodel.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import cn.lixunims.common.enums.CommonSortOrderEnum;
import cn.lixunims.common.exception.CommonException;
import cn.lixunims.common.page.CommonPageRequest;
import cn.lixunims.ims.modular.basics.entity.ImsProductType;
import cn.lixunims.ims.modular.basics.mapper.ImsProductTypeMapper;
import cn.lixunims.ims.modular.basics.param.ImsProductTypeAddParam;
import cn.lixunims.ims.modular.basics.param.ImsProductTypeEditParam;
import cn.lixunims.ims.modular.basics.param.ImsProductTypeIdParam;
import cn.lixunims.ims.modular.basics.param.ImsProductTypePageParam;
import cn.lixunims.ims.modular.basics.service.ImsProductTypeService;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 商品分类Service接口实现类
 *
 * @author YouDong
 * @date  2024/09/16 21:21
 **/
@Service
public class ImsProductTypeServiceImpl extends ServiceImpl<ImsProductTypeMapper, ImsProductType> implements ImsProductTypeService {

    @Override
    public Page<ImsProductType> page(ImsProductTypePageParam imsProductTypePageParam) {
        QueryWrapper<ImsProductType> queryWrapper = new QueryWrapper<ImsProductType>().checkSqlInjection();
        if(ObjectUtil.isNotEmpty(imsProductTypePageParam.getProductTypeName())) {
            queryWrapper.lambda().like(ImsProductType::getProductTypeName, imsProductTypePageParam.getProductTypeName());
        }
        if(ObjectUtil.isAllNotEmpty(imsProductTypePageParam.getSortField(), imsProductTypePageParam.getSortOrder())) {
            CommonSortOrderEnum.validate(imsProductTypePageParam.getSortOrder());
            queryWrapper.orderBy(true, imsProductTypePageParam.getSortOrder().equals(CommonSortOrderEnum.ASC.getValue()),
                    StrUtil.toUnderlineCase(imsProductTypePageParam.getSortField()));
        } else {
            queryWrapper.lambda().orderByAsc(ImsProductType::getProductTypeId);
        }
        return this.page(CommonPageRequest.defaultPage(), queryWrapper);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(ImsProductTypeAddParam imsProductTypeAddParam) {
        ImsProductType imsProductType = BeanUtil.toBean(imsProductTypeAddParam, ImsProductType.class);
        this.save(imsProductType);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(ImsProductTypeEditParam imsProductTypeEditParam) {
        ImsProductType imsProductType = this.queryEntity(imsProductTypeEditParam.getProductTypeId());
        BeanUtil.copyProperties(imsProductTypeEditParam, imsProductType);
        this.updateById(imsProductType);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(List<ImsProductTypeIdParam> imsProductTypeIdParamList) {
        // 执行删除
        this.removeByIds(CollStreamUtil.toList(imsProductTypeIdParamList, ImsProductTypeIdParam::getProductTypeId));
    }

    @Override
    public ImsProductType detail(ImsProductTypeIdParam imsProductTypeIdParam) {
        return this.queryEntity(imsProductTypeIdParam.getProductTypeId());
    }

    @Override
    public ImsProductType queryEntity(String id) {
        ImsProductType imsProductType = this.getById(id);
        if(ObjectUtil.isEmpty(imsProductType)) {
            throw new CommonException("商品分类不存在，id值为：{}", id);
        }
        return imsProductType;
    }

    @Override
    public List<Tree<String>> tree(ImsProductType imsWarehouse) {
        // 获取所有商品分类
        List<ImsProductType> list = this.lambdaQuery()
                .like(StrUtil.isNotBlank(imsWarehouse.getProductTypeName()), ImsProductType::getProductTypeName, imsWarehouse.getProductTypeName())
                .orderByAsc(ImsProductType::getOrderNum)
                .list();

        // 去重
        Set<ImsProductType> wareSet = CollectionUtil.newHashSet(list);

        // 构建 TreeNode，并保留 orderNum 信息
        List<TreeNode<String>> treeNodeList = wareSet.stream().map(ware ->
                        new TreeNode<>(ware.getProductTypeId(), ware.getParentId(),
                                ware.getProductTypeName(), ware.getProductTypeId())
                                .setWeight(ware.getOrderNum()) // 设置排序依据
                                .setExtra(JSONUtil.parseObj(ware)))
                .collect(Collectors.toList());

        // 手动构建树结构并在每一层进行排序
        return TreeUtil.build(treeNodeList, "0");
    }




    @Override
    public List<ImsProductType> getType() {
        List<ImsProductType> result = new ArrayList<ImsProductType>();
        ImsProductType imsWarehouse = new ImsProductType();
        imsWarehouse.setProductTypeId("0");
        imsWarehouse.setParentId(null);
        imsWarehouse.setProductTypeName("顶级");
        result.add(imsWarehouse);


        LambdaQueryChainWrapper<ImsProductType> wrapper = this.lambdaQuery().eq(ImsProductType::getParentId, "0");
        List<ImsProductType> list = wrapper.list();
        result.addAll(list);
        return result;
    }



    @Override
    public void downloadImportInfoTemplate(HttpServletResponse response) throws IOException {
        try {
            InputStream inputStream = POICacheManager.getFile("productTypeAccountImportTemplate.xlsx");
            byte[] bytes = IoUtil.readBytes(inputStream);
            CommonDownloadUtil.download("利讯进销存商品分类导入模板.xlsx", bytes, response);
        } catch (Exception e) {
            log.error(">>> 下载用户导入模板失败：", e);
            CommonResponseUtil.renderError(response, "下载用户导入模板失败");
        }

    }
    @Override
    @Transactional
    public JSONObject importInfo(MultipartFile file) {
        try {
            int successCount = 0;
            int errorCount = 0;
            JSONArray errorDetail = JSONUtil.createArray();
            // 创建临时文件
            File tempFile = FileUtil.writeBytes(file.getBytes(), FileUtil.file(FileUtil.getTmpDir() +
                    FileUtil.FILE_SEPARATOR + "ProductTypeImportTemplate.xlsx"));
            // 读取excel
            List<ImsProductType> sysUserImportParamList =  EasyExcel.read(tempFile).head(ImsProductType.class).sheet()
                    .headRowNumber(2).doReadSync();
            for (int i = 0; i < sysUserImportParamList.size(); i++) {





                try {
                    ImsProductType imsProductType = sysUserImportParamList.get(i);
                    // 处理状态
                    if (imsProductType.getStatus().equals("启用")) {
                        imsProductType.setStatus("ENABLE");
                    } else {
                        imsProductType.setStatus("DISABLED");
                    }

                    // 上级分类
                    String parentName = imsProductType.getParentId();
                    ImsProductType parentWare = this.lambdaQuery().eq(ImsProductType::getProductTypeName, parentName).one();
                    if (parentWare != null) {
                        parentWare.setParentId(parentWare.getParentId());
                    } else {
                        // 创建上级仓库
                        ImsProductType newWare = new ImsProductType();
                        newWare.setParentId("0");
                        newWare.setProductTypeName(parentName);
                        newWare.setStatus("ENABLE");
                        this.save(newWare);
                        newWare.setParentId(newWare.getParentId());
                    }

                    this.save(imsProductType);
                    successCount += 1;
                } catch (Exception e) {
                    errorCount += 1;
                    errorDetail.add("导入失败，请检查第" + (i+1)+"的条数据完整性");
                }
            }
            return JSONUtil.createObj()
                    .set("totalCount", sysUserImportParamList.size())
                    .set("successCount", successCount)
                    .set("errorCount", errorCount)
                    .set("errorDetail", errorDetail);
        } catch (Exception e) {
            log.error(">>> 用户导入失败：", e);
            throw new CommonException("用户导入失败");
        }

    }
    @Override
    public void exportInfo(HttpServletResponse response) throws IOException {
        File tempFile = null;
        try {
            QueryWrapper<ImsProductType> queryWrapper = new QueryWrapper<ImsProductType>().checkSqlInjection();
            String fileName = "利讯进销存系统商品分类清单.xlsx";
            List<ImsProductType> bankAccountList = this.list(queryWrapper);
            if(ObjectUtil.isEmpty(bankAccountList)) {
                throw new CommonException("无数据可导出");
            }
            // transService.transBatch(bankAccountList);
            List<ImsProductType> sysUserExportResultList = bankAccountList.stream().collect(Collectors.toList());
            sysUserExportResultList.remove(0);

            // 处理状态
            for (ImsProductType imsProductType : sysUserExportResultList) {

                if (imsProductType.getProductTypeName().equals("顶级")) {
                    continue;
                }

                if (imsProductType.getStatus().equals("ENABLE")) {
                    imsProductType.setStatus("启用");
                } else {
                    imsProductType.setStatus("禁用");
                }
                // 上级仓库
                String parentId = imsProductType.getParentId();

                ImsProductType parentWare = this.getById(parentId);
                imsProductType.setParentId(parentWare.getProductTypeName());


            }





            // 创建临时文件
            tempFile = FileUtil.file(FileUtil.getTmpDir() + FileUtil.FILE_SEPARATOR + fileName);

            // 头的策略
            WriteCellStyle headWriteCellStyle = new WriteCellStyle();
            WriteFont headWriteFont = new WriteFont();
            headWriteFont.setFontHeightInPoints((short) 14);
            headWriteCellStyle.setWriteFont(headWriteFont);
            // 水平垂直居中
            headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
            headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);

            // 内容的策略
            WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
            // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定
            contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
            // 内容背景白色
            contentWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
            WriteFont contentWriteFont = new WriteFont();

            // 内容字体大小
            contentWriteFont.setFontHeightInPoints((short) 12);
            contentWriteCellStyle.setWriteFont(contentWriteFont);

            //设置边框样式，细实线
            contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);
            contentWriteCellStyle.setBorderTop(BorderStyle.THIN);
            contentWriteCellStyle.setBorderRight(BorderStyle.THIN);
            contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);

            // 水平垂直居中
            contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.LEFT);
            contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);

            // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现
            HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(headWriteCellStyle,
                    contentWriteCellStyle);

            // 写excel
            EasyExcel.write(tempFile.getPath(), ImsProductType.class)
                    // 自定义样式
                    .registerWriteHandler(new AbstractColumnWidthStyleStrategy() {
                        @Override
                        protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
                            Sheet sheet = writeSheetHolder.getSheet();
                            sheet.setColumnWidth(cell.getColumnIndex(), 20 * 256); // 设置所有列宽为30个字符宽度
                        }
                    })
                    // 自动列宽
                    .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                    // 设置第一行字体
                    .registerWriteHandler(new CellWriteHandler() {
                        @Override
                        public void afterCellDispose(CellWriteHandlerContext context) {
                            WriteCellData<?> cellData = context.getFirstCellData();
                            WriteCellStyle writeCellStyle = cellData.getOrCreateStyle();
                            Integer rowIndex = context.getRowIndex();
                            if(rowIndex == 0) {
                                WriteFont headWriteFont = new WriteFont();
                                headWriteFont.setFontName("宋体");
                                headWriteFont.setBold(true);
                                headWriteFont.setFontHeightInPoints((short) 16);
                                writeCellStyle.setWriteFont(headWriteFont);
                            }
                        }
                    })
                    // 设置表头行高
                    .registerWriteHandler(new AbstractRowHeightStyleStrategy() {
                        @Override
                        protected void setHeadColumnHeight(Row row, int relativeRowIndex) {
                            if(relativeRowIndex == 0) {
                                // 表头第一行
                                row.setHeightInPoints(34);
                            } else {
                                // 表头其他行
                                row.setHeightInPoints(30);
                            }
                        }
                        @Override
                        protected void setContentColumnHeight(Row row, int relativeRowIndex) {
                            // 内容行
                            row.setHeightInPoints(20);
                        }
                    })
                    .sheet("商品分类信息")
                    .relativeHeadRowIndex(1)
                    .doWrite(sysUserExportResultList);
            CommonDownloadUtil.download(tempFile, response);
        } catch (Exception e) {
            log.error(">>> 商品分类导出失败：", e);
            CommonResponseUtil.renderError(response, "商品分类导出失败");
        } finally {
            FileUtil.del(tempFile);
        }

    }

}
